package com.sprometheus.core.aspect;

import cn.hutool.core.date.StopWatch;
import com.sprometheus.core.anno.SPrometheus;
import com.sprometheus.core.handler.SPrometheusHandler;
import com.sprometheus.core.pojo.SPrometheusException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

import javax.annotation.Resource;

/**
 * @author Goslee
 * @date 2024/9/5 下午4:56
 */
@Aspect
@Slf4j
public class GlobalExceptionAspect {

    @Resource
    private SPrometheusHandler prometheusHandler;

    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
    public void getRequestMapping() {
    }

    @Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")
    public void getGetMapping() {
    }

    @Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping)")
    public void getPostMapping() {
    }

    /**
     * 系统异常、业务监控异常
     *
     * @param point
     * @return
     */
    @Around("getRequestMapping() || getGetMapping() || getPostMapping()")
    public Object insertExp(ProceedingJoinPoint point) throws Throwable {
        //开始时间用于计算接口耗时
        StopWatch watch = new StopWatch();
        watch.start();
        Object r = null;
        try {
            r = point.proceed(point.getArgs());
        } catch (SPrometheusException e) {
            //指定异常
            watch.stop();
            prometheusHandler.handlePrometheusExp(point, watch, e);
            throw e;
        } catch (Exception e) {
            //系统异常
            watch.stop();
            //是否存在监听注解
            if (((MethodSignature) point.getSignature()).getMethod().isAnnotationPresent(SPrometheus.class)) {
                prometheusHandler.handlePrometheusOtherExp(point, watch, e);
            } else {
                prometheusHandler.handleDefault(point, watch, e);
            }
            throw e;
        }
        return r;
    }

}
